package control;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Set;

import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ResponseBody;

import bean.Client;
import bean.Flight;
import bean.Hotel;
import bean.Panel;
import bean.User;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

@Service
public class Dao {
	
	//Dao dao = new Dao();
	
	private String nomPersist = "tphibernate";
	
	EntityManagerFactory emf = null;
	EntityManager entityManager = null;

	public Dao() {
		System.out.println("Dao xxxxx");
		emf = Persistence.createEntityManagerFactory(nomPersist);
		entityManager = emf.createEntityManager();

	}
	
	public void enregistrerClient(Client c) {
		EntityTransaction tx = entityManager.getTransaction();
		tx.begin();
		entityManager.persist(c);
		tx.commit();
	}
	
	public List<Client>listerClients()  {
		List <Client> lst = entityManager.createQuery(
				"select g from Client g").getResultList();
		return lst;
	}

		
	public void ouvrir() {
		emf = Persistence.createEntityManagerFactory(nomPersist);
		entityManager = emf.createEntityManager();
	}

	public void fermer() {
		entityManager.close();
		emf.close();
	}
	
	
	
	
	// Ajoute un utilisateur
		public User addUser(String name, String password, String mail){
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			User newUser = new User(name, password, mail);
			
			entityManager.persist(newUser);
			entityManager.getTransaction().commit();

			return newUser;
		}

		// Suppression d'un utilisateur
		public boolean removeUser(int idUser){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();

			String hqlDelete = "delete User where id = :idRemov";
			int deletedEntities = entityManager.createQuery( hqlDelete ).setParameter( "idRemov", idUser ).executeUpdate();
			System.out.println(deletedEntities);
			entityManager.getTransaction().commit();
			
			if(deletedEntities == 1)
				return true;
			else
				return false;
			
		}
		
		// M�thode de mise � jour d'un utilisateur
		public boolean modifiyUser(int idxUser, String name, String password, String email){
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();

			Query query = entityManager.createQuery("update User as u set u.name = :nameUser, u.password = :passwordUser, email = :emailUser " + 
			" where id = :idxUser");
			query.setParameter("idxUser", idxUser);
			query.setParameter("nameUser", name);
			query.setParameter("passwordUser", password);
			query.setParameter("emailUser", email);
			int result = query.executeUpdate();

			entityManager.getTransaction().commit();
			
			// R�sultat de la requ�te de mise � jour
			if (result == 1)
				return true;
			return false;
		}
		
		// M�thode d'authentification, pour v�rifier que la connexion est bien possible
		// il est n�cessaire de renseigner deux param�tres : le login et le mot de passe.
		public boolean connexionUser(String log, String password){
			Query query = entityManager.createQuery("from User as u where u.name= :login and u.password = :password");
			query.setParameter("login", log);
			query.setParameter("password", password);
			List list = query.getResultList();
			if(list.size() >= 1)
				return true;
			return false;
		}
		
		// Retourne un objet utilisateur par rapport � un identifiant pass� en param�tre
		public User getUser( int idxUser){
			User user = (User) entityManager.find(User.class, new Integer(idxUser));
			return user;
		}
		
		// Retourne les utilisateurs de la BDD
		public List<User> getUsers(){
			
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			List<User> listUsers = entityManager.createQuery("FROM User").getResultList();
			
			return listUsers;
		}

		// Ajoute un hotel
		public Hotel addHotel(String name, String address, String classification){
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			Hotel newHotel = new Hotel(name, address, classification);
			
			entityManager.persist(newHotel);
			entityManager.getTransaction().commit();

			return newHotel;
		}

		// Suppression d'un hotel
		public boolean removeHotel(int idHotel){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();

			String hqlDelete = "delete Hotel where id = :idRemov";
			int deletedEntities = entityManager.createQuery( hqlDelete ).setParameter( "idRemov", idHotel ).executeUpdate();
			System.out.println(deletedEntities);
			entityManager.getTransaction().commit();
			
			if(deletedEntities == 1)
				return true;
			else
				return false;
		}

		// M�thode de mise � jour d'un hotel
		public boolean modifiyHotel(int idxHotel, String name, String address, String classification){
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();

			Query query = entityManager.createQuery("update Hotel as u set u.name = :nameHotel, u.address = :addressHotel, u.classification = :classificationHotel " + 
			" where id = :idxHotel");
			query.setParameter("idxHotel", idxHotel);
			query.setParameter("nameHotel", name);
			query.setParameter("addressHotel", address);
			query.setParameter("classificationHotel", classification);
			int result = query.executeUpdate();

			entityManager.getTransaction().commit();
			
			// R�sultat de la requ�te de mise � jour
			if (result == 1)
				return true;
			return false;
		}
		
		// Retourne un objet Hotel par rapport � un identifiant pass� en param�tre
		public Hotel getHotel( int idxHotel){
			Hotel hotel = (Hotel) entityManager.find(Hotel.class, new Integer(idxHotel));
			return hotel;
		}
		
		// Retourne la liste des hotels de la BDD
		public List<Hotel> getHotels(){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
				List<Hotel> listHotels = entityManager.createQuery("FROM Hotel").getResultList();
			
			return listHotels;
		}
		
		// Ajoute un vol
		public Flight addFlight(String name, String departureTown, Date departureTime, String arrivalTown, Date arrivalTime){
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			Flight newFlight = new Flight(name, departureTown, departureTime, arrivalTown, arrivalTime);
			
			entityManager.persist(newFlight);
			entityManager.getTransaction().commit();

			return newFlight;
		}

		// Suppression d'un vol
		public boolean removeFlight(int idFlight){
			
			Flight flight = getFlight(idFlight);
			ArrayList<Panel> lstPanels = getPanelsAttachToFlight(flight);
			for (Panel panel : lstPanels) {
				removePanel(panel.getId());
			}

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			String hqlDelete = "delete Flight where id = :idRemov";
			int deletedEntities = entityManager.createQuery( hqlDelete ).setParameter( "idRemov", idFlight ).executeUpdate();
			System.out.println(deletedEntities);
			entityManager.getTransaction().commit();
			
			if(deletedEntities == 1)
				return true;
			else
				return false;
		}

		// M�thode de mise � jour d'un vol
		public boolean modifiyFlight(int idxFlight, String name, String departureTown, Date departureTime, String arrivalTown, Date arrivalTime){
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();

			Query query = entityManager.createQuery("update Flight as f set f.name = :nameFlight, f.departureTown = :departureTownFlight, f.departureTime = :departureTimeFlight, f.arrivalTown = :arrivalTownFlight, f.arrivalTime = :arrivalTimeFlight " + 
			" where id = :idxFlight");
			query.setParameter("idxFlight", idxFlight);
			query.setParameter("nameFlight", name);
			query.setParameter("departureTownFlight", departureTown);
			query.setParameter("departureTimeFlight", departureTime);
			query.setParameter("arrivalTownFlight", arrivalTown);
			query.setParameter("arrivalTimeFlight", arrivalTime);		
			int result = query.executeUpdate();

			entityManager.getTransaction().commit();
			
			// R�sultat de la requ�te de mise � jour
			if (result == 1)
				return true;
			return false;
		}
		
		// Retourne un objet Flight par rapport � un identifiant pass� en param�tre
		public Flight getFlight( int idxFlight){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			Flight flight = (Flight) entityManager.find(Flight.class, new Integer(idxFlight));
			return flight;
		}
		
		// Retourne la liste des hotels de la BDD
		public List<Flight> getFlights(){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			List<Flight> listFlights = entityManager.createQuery("select g from Flight g").getResultList();
			//List<Flight> listFlights = entityManager.createQuery("FROM Flight").getResultList();
			return listFlights;
		}

		// M�thode permettant d'ajout un hotel � un vol
		public Flight addHotelToFlight(Integer idxFlight, Integer idxHotel){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			Flight flight = getFlight(idxFlight);
			Hotel hotel = getHotel(idxHotel);
			
			Set<Hotel> listHotels = flight.getHotels();
			listHotels.add(hotel);
			
			flight.setHotels(listHotels);
			
			entityManager.persist(flight);
			entityManager.getTransaction().commit();
			
			return flight;
		}
		
		
		// M�thode permettant de supprimer un hotel � un vol
		public Flight removeHotelToFlight(Integer idxFlight, Integer idxHotel){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();

			Flight flight = getFlight(idxFlight);
			Hotel hotel = getHotel(idxHotel);

			Set<Hotel> listHotels = flight.getHotels();
			listHotels.remove(hotel);
			
			entityManager.persist(flight);
			entityManager.getTransaction().commit();
			
			return flight;
		}
		
		public Flight addHotelsToFlight(Integer idxFlight, List<Integer> idsHotel)
		{
			Flight flight = null;
			for(Integer idxHotel : idsHotel)
				flight = addHotelToFlight(idxFlight, idxHotel);
			
			return flight;
		}
		
		// Ajoute d'un panneau
		public Panel addPanel(String name, Date hourOfDisplay, Integer idxFlight){
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			Panel newPanel = new Panel(getFlight(idxFlight), name, hourOfDisplay);
			
			entityManager.persist(newPanel);
			entityManager.getTransaction().commit();

			return newPanel;
		}

		// Suppression d'un panneau
		public boolean removePanel(int idPanel){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();

			String hqlDelete = "delete Panel where id = :idRemov";
			int deletedEntities = entityManager.createQuery( hqlDelete ).setParameter( "idRemov", idPanel ).executeUpdate();
			System.out.println(deletedEntities);
			entityManager.getTransaction().commit();
			
			if(deletedEntities == 1)
				return true;
			else
				return false;
		}

		// M�thode de mise � jour d'un panneau
		public boolean modifiyPanel(int idxPanel, String name, Date hourOfDisplay, Integer idxFlight){
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();

			Query query = entityManager.createQuery("update Panel as p set p.name = :namePanel, p.hourOfDisplay = :hourOfDisplayPanel, flight = :flightPanel " + 
			" where id = :idxPanel");
			query.setParameter("idxPanel", idxPanel);
			query.setParameter("namePanel", name);
			query.setParameter("hourOfDisplayPanel", hourOfDisplay);
			query.setParameter("flightPanel", getFlight(idxFlight));
			int result = query.executeUpdate();

			entityManager.getTransaction().commit();
			
			// R�sultat de la requ�te de mise � jour
			if (result == 1)
				return true;
			return false;
		}
		
		// Retourne un objet "Panneau" par rapport � un identifiant pass� en param�tre
		public Panel getPanel( int idxPanel){			
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			Panel panel = (Panel) entityManager.find(Panel.class, new Integer(idxPanel));
			return panel;
		}
		
		// Retourne la liste des panneaux de la BDD
		public List<Panel> getPanels(){

			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
				List<Panel> listPanels = entityManager.createQuery("FROM Panel").getResultList();
			
			return listPanels;
		}
	
		public Panel getPanelToDisplay(){
			
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			Date date = new Date();
			Calendar beginDate = GregorianCalendar.getInstance();
			beginDate.setTime(date);

			Query query = entityManager.createQuery("FROM Panel where EXTRACT( HOUR FROM hourOfDisplay ) = :beginDate AND EXTRACT( MINUTE FROM hourOfDisplay ) BETWEEN 0 AND 59");
			query.setParameter("beginDate", beginDate.get(Calendar.HOUR_OF_DAY));
			List list = query.getResultList();
			System.out.println("getPanelToDisplay() => res =" + list.size());
			
			System.out.println("getPanelToDisplay() => res =" + list.size());
			if(list.size() >= 1)
				return (Panel) list.get(0);
			else
				return null;
		}
		
		public ArrayList<Panel> getPanelsAttachToFlight(Flight flight){
			
			if(!entityManager.getTransaction().isActive())
				entityManager.getTransaction().begin();
			
			Date date = new Date();
			Calendar beginDate = GregorianCalendar.getInstance();
			beginDate.setTime(date);

			Query query = entityManager.createQuery("FROM Panel where flight = :objFlight");
			query.setParameter("objFlight", flight);
			List list = query.getResultList();
			
			return (ArrayList<Panel>) list;
		}
		
	public void init() {
		System.out.println("init dao");
	}

}
